/**
 * @file Common utility functions.
 * @author Zmei Zelen <zmei.zelen@gmail.com>
 */

/**
 * Namespace for several helper funcuitons.
 * @type Object
 */
var Utils = {};

// TODO: documentation!
Utils.adopt = function(sub, sup) {
    var copy = function(sub, sup) {
        for (var field in sup) {
            sub.prototype[field] = sup[field];
        }
    };

    if (sup instanceof Array) {
        sub.prototype.super = {};
        var id = 0;
        for (var id, length = sup.length; id < length; id++) {
            copy(sub, sup[id]);
            if (typeof sup.name === "string" && sup.name) {
                sub.prototype.super[sup.name] = sup;
            } else {
                sub.prototype.super[(id++).toString()] = sup;
            }
        }
    } else {
        copy(sub, sup);
        sub.prototype.super = sup;
    }
};

Utils.extend = function(sub, sup) {
    function glue() {
    }
    glue.prototype = sup.prototype;
    sub.prototype = new glue();
    sub.prototype.constructor = sub;
    sub.prototype.super = sup.prototype;
};

Utils.merge = function(/* destination, sources, ... */) {
    var _arguments = Array.prototype.slice.call(arguments),
            destination = _arguments.shift();
    do {
        var source = _arguments.shift();
        if (!source) source = new Object;
        if (source) {
            for (var field in source) {
                if (source.hasOwnProperty(field)) {
                    destination[field] = source[field];
                }
            }
        } 
    } while (source);
    return destination;
};

Utils.copy = function (object) {
    var result = new Object();
    for (var field in object) {
        if (object.hasOwnProperty(field)) {
            result[field] = object[field];
        }
    }
    return result;
};



function Vector2d(x, y) {
    this.x = x;
    this.y = y;
}

Vector2d.prototype.sum = function(value, factor) {
    if (factor === undefined) factor = 1;
    if (typeof value === 'number') {
        this.x += value * factor;
        this.y += value * factor;
    } else if (value instanceof Vector2d) {
        this.x += value.x * factor;
        this.y += value.y * factor;
    } else throw "The value must be number or Vector2d.";
    return this;
};

Vector2d.prototype.mul = function(scalar) {
    this.x *= scalar;
    this.y *= scalar;
    return this;
};

Vector2d.prototype.len2 = function() {
    return Math.pow(this.x, 2) + Math.pow(this.y, 2);
};

Vector2d.prototype.len = function() { return this.len2(); };

Vector2d.prototype.diff2 = function(vector) {
    return Math.pow(this.x - vector.x, 2) + Math.pow(this.y - vector.y, 2);
};

Vector2d.prototype.diff = function(vector) {
    return Math.sqrt(this.diff(vector));
};

Vector2d.prototype.copy = function () {
    return new Vector2d(this.x, this.y);
}